package com.vueapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vueapi.constant.CommonEnum;
import com.vueapi.constant.ErrorCodeEnum;
import com.vueapi.domain.HjComment;
import com.vueapi.domain.dto.CommentSearchDTO;
import com.vueapi.domain.vo.CommentsVo;
import com.vueapi.exception.BlogException;
import com.vueapi.mapper.HjCommentMapper;
import com.vueapi.service.HjCommentService;
import com.vueapi.utils.*;
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
import net.dreamlu.mica.ip2region.core.IpInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 15442
 * @description 针对表【hj_comment】的数据库操作Service实现
 * @createDate 2022-09-20 11:44:51
 */
@Service
public class HjCommentServiceImpl extends ServiceImpl<HjCommentMapper, HjComment>
        implements HjCommentService{

    @Autowired
    private Ip2regionSearcher ip2regionSearcher;

    @Override
    public Integer getCount() {
        return this.baseMapper.getCount();
    }

    @Override
    public List<Integer> getCommentAddCount() {
        ArrayList<Integer> dataCountVOS = new ArrayList<>();
        for (int i = 7; i >= 1; i--) {

            Date today = TimeAgoUtils.getTodayZeroTimePre(i);
            Date lastDay = null;
            // 0代表了今天，那么就要算今天到明天，所以要调用往后加天数的方法 暂时取消
            lastDay = TimeAgoUtils.getTodayZeroTimePre(i-1);

            LambdaQueryWrapper<HjComment> between = new LambdaQueryWrapper<HjComment>().select(HjComment::getId).between(HjComment::getCreateTime,today, lastDay);
            dataCountVOS.add((int) count(between));
        }
        return dataCountVOS;
    }

    @Override
    public boolean add(HjComment comment){

        // 限制评论数量
        Integer count = this.getCount();
        if(count >= 1000){
            return false;
        }

        // 限制评论长度
        if(comment.getContent().length() > 64){
            throw new BlogException(ErrorCodeEnum.COMMENT_LENGTH_MORE.getCode(),ErrorCodeEnum.COMMENT_LENGTH_MORE.getMsg());
        }

        // 获取IP
        HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
        String ip = IPUtils.getIpAddr(request);
        IpInfo ipInfo = ip2regionSearcher.memorySearch(ip);
        String address = "UNKNOWN";
        if(ipInfo != null){
            address = ipInfo.getAddress();
        }

        // 设置默认头像
        if(comment.getWebsiteUrl() == null || comment.getWebsiteUrl().equals("")){
            comment.setWebsiteUrl("http://img.linzhongyue.cn/jiaozi.jpg");
        }

        // 存入数据库
        comment.setStatus(CommonEnum.CommentAuditStatus.WAIT.getCode());
        comment.setIp(ip);
        comment.setIpSource(address);

        return this.save(comment);
    }

    @Override
    public ArrayList<CommentsVo>  getCommentsByBlogId(Integer blogId) {

        long start = System.currentTimeMillis();

        ArrayList<CommentsVo> commentsVos = new ArrayList<>();

        // 先获取该博客下的所有评论
        List<HjComment> commentList = this.list(new LambdaQueryWrapper<HjComment>()
                .eq(HjComment::getBlogId, blogId)
                .eq(HjComment::getStatus,CommonEnum.CommentAuditStatus.SUCCESS.getCode())
                .orderByAsc(HjComment::getCreateTime));

        // 获取所有父级评论
        List<HjComment> level1 = commentList.stream().filter(c -> c.getLevel() == CommonEnum.CommentLevel.F.getCode()).collect(Collectors.toList());

        // 获取所有子级评论
        List<HjComment> level2 = commentList.stream().filter(c -> c.getLevel() == CommonEnum.CommentLevel.S.getCode()).collect(Collectors.toList());

        // 遍历父级评论
        for (HjComment l1 : level1) {
            CommentsVo commentsVo = new CommentsVo();
            BeanUtils.copyProperties(l1,commentsVo);
            ArrayList<CommentsVo> replyCommentsVos = new ArrayList<>();

            // 评论发布时间
            commentsVo.setTimeAgo(TimeAgoUtils.format(l1.getCreateTime()));

            // 遍历子级评论
            for (HjComment l2 : level2) {
                if(l2.getParentId() == null || l2.getParentId() == 0){
                    continue;
                }

                // 如果父级ID为当前的评论ID且等级为子级，就添加入集合
                if(l2.getParentId().equals(l1.getId())){
                    CommentsVo replyCommentVo = new CommentsVo();
                    BeanUtils.copyProperties(l2,replyCommentVo);
                    // 评论发布时间
                    replyCommentVo.setTimeAgo(TimeAgoUtils.format(l2.getCreateTime()));
                    replyCommentsVos.add(replyCommentVo);
                }
            }
            commentsVo.setReplies(replyCommentsVos);
            commentsVos.add(commentsVo);
        }

        System.out.println("评论查找共花费: " + (System.currentTimeMillis() - start) + " 毫秒");
        return commentsVos;
    }

    @Override
    public ResultUtils listPage(Integer pageNum, Integer pageSize, CommentSearchDTO searchDTO) {
        LambdaQueryWrapper<HjComment> cw = new LambdaQueryWrapper<>();
        cw.eq(searchDTO.getBlogId() != null,HjComment::getBlogId,searchDTO.getBlogId());
        cw.eq(!searchDTO.getCommentator().equals(""),HjComment::getCommentator,searchDTO.getCommentator());
        cw.eq(!Objects.equals(searchDTO.getEmail(), ""),HjComment::getEmail,searchDTO.getEmail());
        cw.like(!Objects.equals(searchDTO.getIpSource(), ""),HjComment::getIpSource,searchDTO.getIpSource());
        cw.eq(searchDTO.getLevel() != null,HjComment::getLevel,searchDTO.getLevel());
        cw.eq(searchDTO.getStatus() != null,HjComment::getStatus,searchDTO.getStatus());
        cw.eq(HjComment::getIsDeleted,0);
        cw.orderByDesc(HjComment::getCreateTime);

        Page<HjComment> commentPage = this.page(new Page<>(pageNum, pageSize), cw);

        return ResultUtils.success(commentPage);
    }

    @Override
    public Boolean commentDeleteByIds(String ids) {

        try {
            List<Integer> commentIds = ParseUtils.intArrayToList(ParseUtils.stringToIntArray(ids));

            for (Integer id : commentIds) {
                HjComment comment = this.getById(id);
                // 如果是父级就要删除父级下的所有评论
                // 如果不是父级直接删除即可
                if(comment.getLevel() == CommonEnum.CommentLevel.F.getCode()){
                    List<HjComment> removeComments = this.list(new LambdaQueryWrapper<HjComment>().eq(HjComment::getLevel, CommonEnum.CommentLevel.S.getCode()).eq(HjComment::getParentId, id));
                    // 如果没有子级评论则跳过
                    if(CollectionUtil.isNotEmpty(removeComments)){
                        List<Integer> removeIds = removeComments.stream().map(HjComment::getId).collect(Collectors.toList());
                        this.removeByIds(removeIds);
                    }
                }
                this.removeById(id);
            }
            return true;
        }catch (Exception e){
            throw new BlogException(ErrorCodeEnum.DELETE_COMMENT_ERROR.getCode(), ErrorCodeEnum.DELETE_COMMENT_ERROR.getMsg());
        }
    }

    @Override
    public Boolean auditPass(String ids) {
        try {
            List<Integer> commentIds = ParseUtils.intArrayToList(ParseUtils.stringToIntArray(ids));

            for (Integer id : commentIds) {
                HjComment comment = new HjComment();
                comment.setId(id);
                comment.setStatus(CommonEnum.CommentAuditStatus.SUCCESS.getCode());
                this.updateById(comment);
            }

            return true;
        }catch (Exception e){
            throw new BlogException(ErrorCodeEnum.AUDIT_COMMENT_ERROR.getCode(), ErrorCodeEnum.AUDIT_COMMENT_ERROR.getMsg());
        }
    }
}




